package com.acme.bankapp.domain;

import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.acme.bankapp.domain.Client;
import com.acme.bankapp.ClientRegistrationListeners.ClientRegistrationListener;
import com.acme.bankapp.exception.*;

/**
 * Class of bank contains fields: listeners and clients, representing, respectively, the list of listeners and a list of clients.
 * Class methods:
 * public void printAllClients(): Print a list of clients.
 * public void printBalance(): Print a list of the bank balance sheets.
 * public void addClient(Client client) : Adding a client to the list clients.
 * public void withdrawClient(Client client, double x): Withdrawal the client balance of magnitude x.
 * public void depositeClient(Client client, double x): Increase the balance on the delta.
 * public void printClient(Client client): Print selected client.
 * public Client searchClient(String searchFirstName, String searchLastName): Searching for a client in the list clients.
 * The nested class DebugListener that contains the method void onAddClient(Client client) output to the console client's name and the current time.
 * The nested class PrintClientListener that contains the method void onAddClient(Client client) output to the console all information about the client.
 * The nested class EmailNotificationListener thst contains the method void onAddClient(Client client) output notification email.
 * @author Troitskaya Anastasia
 *
 */

public class Bank {
	private List<Client> clients;
	private List<ClientRegistrationListener> listeners;
	public Bank() {
		this.clients = new LinkedList<Client>();
		this.listeners = new LinkedList<ClientRegistrationListener>();
		listeners.add(new PrintClientListener());
		listeners.add(new EmailNotificationListener());
		listeners.add(new DebugListener());
	}
	public void printAllClients() {
		for (Client client: clients) {
			System.out.println(client.getGender().getSalutation()+" "+client.getFirstName()+" "+client.getLastName());
		}
	}
	public void printBalance() {
		for (Client client: clients) {
			System.out.println(client.getAccount().getBalance());
		}
	}
	public void addClient(Client client) {
		assert(client != null);
		try {
			if (!(clients.contains(client))) {
				clients.add(client);
				for (ClientRegistrationListener listener: listeners) {
					listener.onClientAdd(client);
				}
			}
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			System.out.println("There is this client already");
		}
	}
	public void withdrawClient(Client client, double x) {
		try {
			if (client != null) {
				try {
					client.getAccount().withdraw(x);
				}
				catch (OverDraftLimitExceededException e) {
					System.out.println("Balance is "+e.getBalance()+",maxCredit is "+e.getMaxCredit());
				}
				catch (NotEnoughFundsException e) {
					System.out.println("There is no such money");
				}
			}
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			System.out.println("There is no such client");
		}
	}
	public void depositeClient(Client client, double x) {
		try {
			if (client != null)
				client.getAccount().deposite(x);
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			System.out.println("There is no such client");
		}
	}
	public void printClient(Client client) {
		try {
			if (client != null)
				System.out.println(client.getGender().getSalutation()+" "+client.getFirstName()+" "+client.getLastName()+" "+client.getAccount().getBalance()+",maxCredit= "+client.getAccount().maxCredit());
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			System.out.println("There is no such client");
		}
	}
	public Client searchClient(String searchFirstName, String searchLastName) {
		for (Client client: clients) {
			final String firstName = client.getFirstName();
			final String lastName = client.getLastName();
			if ((firstName.equals(searchFirstName))&&(lastName.equals(searchLastName))) {
				return client;
			}
		}
		return null;
	}
	class DebugListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
			String s = df.format(new Date());
			System.out.println(client.getGender()+" "+client.getFirstName()+" "+client.getLastName()+" "+s);
		}
	}
	class PrintClientListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			System.out.println(client.getGender()+" "+client.getFirstName()+" "+client.getLastName()+" "+client.getAccount().getBalance()+" "+client.getAccount().maxCredit());
		}
	}
	class EmailNotificationListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			System.out.println("Notification email for "+client.getGender()+" "+client.getFirstName()+" "+client.getLastName()+" to be sent");
		}
	}
}
